﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Checkers_Beta
{
    public partial class GameWindow : Form
    {
        //Image resources
        Bitmap WhitePiece = Properties.Resources.plainWhite48,
        BlackPiece        = Properties.Resources.plainBlack48,
        WhitePieceK       = Properties.Resources.plainWhiteKing48,
        BlackPieceK       = Properties.Resources.plainBlackKing48,
        imgEmpty          = new Bitmap(1, 1);

        //Tile Colors
        Color FG = Color.FromArgb(1, 16, 29);
        Color BG = Color.FromArgb(248, 248, 248);
        Color SC = Color.FromArgb(0, 123, 198);

        //The last selected index
        Data.Cell currentCell = new Data.Cell();

        //Turn based conditon
        bool isPlayerSelected = false;

        //NB: Use the inbuilt functions, instead of direct accesss
        Data.TileState[] BoardData = new Data.TileState[64];

        //White goes first
        Data.TurnState TurnSwitch = Data.TurnState.white;

        //Scores
        int WhiteScore = 0;
        int BlackScore = 0;
        int TilesLeft = 64;
        //Initialize designer code
        public GameWindow()
        {
            InitializeComponent();
            SetupGame();
            this.Load += new EventHandler(Window_Load);
            this.Resize += new EventHandler(Window_Resize);
            CenterBoard();
        }
        void ResetScore()
        {
            WhiteScore = 0;
            BlackScore = 0;
            txtWScore.Text = "White: 0";
            txtBScore.Text = "Black: 0";
        }
        void SetScore(int white=0, int black=0)
        {
            WhiteScore += white;
            BlackScore += black;
            txtWScore.Text = "White: " + WhiteScore;
            txtBScore.Text = "Black: " + BlackScore;
        }
        void Window_Load(object sender, EventArgs e)
        {
            RestartGame();
        }
        void Window_Resize(object sender, EventArgs e)
        {
            CenterBoard();
            BoardLayout.Show();
        }
        //Application menu
        private void mnuClose_Click(object sender, EventArgs e)
        {
            Close();
        }
        private void mnuHi_Click(object sender, EventArgs e)
        {
            ScoreDialog scores = new ScoreDialog();
            scores.ShowDialog();
        }
        //UI Feature: Show about dialog
        private void mnuAbout_Click(object sender, EventArgs e)
        {
            AboutDialog about = new AboutDialog();
            about.ShowDialog();
        }
        //UI Feature: Restart game
        private void mnuRestart_Click(object sender, EventArgs e)
        {
            BoardLayout.Hide();
            RestartGame();
            BoardLayout.Show();
        }
        void CenterBoard()
        {
            BoardLayout.Left = ClientSize.Width / 2 - (BoardLayout.Width / 2);
            BoardLayout.Top = ClientSize.Height / 2 - (BoardLayout.Height / 2) + (AppMenu.Height / 2) - (panel1.Height / 2);
        }
        bool ClickWhite_Move(Data.Cell cell)
        {
            log("ClickWhite_Move: cell " + cell.Index());
            bool complete = false;
            bool king = false;
            Data.TileState result = GetState(cell.Index());
            if ((result & Data.TileState.white) == Data.TileState.white || ((result & Data.TileState.wking)
                == Data.TileState.wking) && (result & Data.TileState.black) != Data.TileState.black &&
                ((result & Data.TileState.bking) != Data.TileState.bking)) 
            {
                isPlayerSelected = true;
                currentCell = cell;
                SetTileColor(currentCell.Index(), SC);
            }
            else
            {
                Data.Cell CDest = cell;
                Data.MoveType CMove;
                if (GetState(currentCell.Index()) == Data.TileState.wking) king = true;
                CMove = WhiteMove(currentCell, CDest, king);
                if (CMove == Data.MoveType.invalid)
                {
                    isPlayerSelected = false;
                }
                else
                {
                    if (CMove != Data.MoveType.invalid)
                    {
                                        
                        if (CDest.row == Data.PlayerGoal)
                        {
                            king = true;
                        }
                        if (CMove == Data.MoveType.takeNW)
                        {
                            Data.Cell NW = CDest;
                            NW.row++;
                            NW.col++;
                            SetState(NW.Index(), Data.TileState.empty);
                            SetScore(1);
                        }
                        if (CMove == Data.MoveType.takeNE)
                        {
                            Data.Cell NE = CDest;
                            NE.row++;
                            NE.col--;
                            SetState(NE.Index(), Data.TileState.empty);
                            SetScore(1);
                        }
                        if (CMove == Data.MoveType.takeSW)
                        {
                            Data.Cell SW = CDest;
                            SW.col++;
                            SW.row--;
                            SetState(SW.Index(), Data.TileState.empty);
                            SetScore(1);
                        }
                        if (CMove == Data.MoveType.takeSE)
                        {
                            Data.Cell SE = CDest;
                            SE.col--;
                            SE.row--;
                            SetState(SE.Index(), Data.TileState.empty);
                            SetScore(1);
                        }
                        if(king)
                            DoMove(currentCell.Index(), CDest.Index(), Data.TileState.wking);
                        else
                            DoMove(currentCell.Index(), CDest.Index(), GetState(currentCell.Index()));
                        complete = true;
                    }
                }
            }
            return complete;
        }
        bool ClickBlack_Move(Data.Cell cell)
        {
            log("ClickBlack_Move: cell " + cell.Index());
            bool complete = false;
            bool king = false;
            Data.TileState result = GetState(cell.Index());
            if ((result & Data.TileState.black) == Data.TileState.black || ((result & Data.TileState.bking)
                == Data.TileState.bking) && (result & Data.TileState.white) != Data.TileState.white &&
                ((result & Data.TileState.wking) != Data.TileState.wking))
            {
                isPlayerSelected = true;
                currentCell = cell;
                SetTileColor(currentCell.Index(), SC);
            }
            else
            {
                Data.Cell CDest = cell;
                Data.MoveType CMove;
                if (GetState(currentCell.Index()) == Data.TileState.bking) king = true;
                CMove = BlackMove(currentCell, CDest, king);
                if (CMove == Data.MoveType.invalid)
                {
                    isPlayerSelected = false;
                }
                else
                {
                    if (CMove != Data.MoveType.invalid)
                    {

                        if (CDest.row == Data.AIGoal)
                        {
                            king = true;
                        }
                        if (CMove == Data.MoveType.takeNW)
                        {
                            Data.Cell NW = CDest;
                            NW.row++;
                            NW.col++;
                            SetState(NW.Index(), Data.TileState.empty);
                            SetScore(0, 1);
                        }
                        if (CMove == Data.MoveType.takeNE)
                        {
                            Data.Cell NE = CDest;
                            NE.row++;
                            NE.col--;
                            SetState(NE.Index(), Data.TileState.empty);
                            SetScore(0, 1);
                        }
                        if (CMove == Data.MoveType.takeSW)
                        {
                            Data.Cell SW = CDest;
                            SW.col++;
                            SW.row--;
                            SetState(SW.Index(), Data.TileState.empty);
                            SetScore(0, 1);
                        }
                        if (CMove == Data.MoveType.takeSE)
                        {
                            Data.Cell SE = CDest;
                            SE.col--;
                            SE.row--;
                            SetState(SE.Index(), Data.TileState.empty);
                            SetScore(0, 1);
                        }
                        if (king)
                            DoMove(currentCell.Index(), CDest.Index(), Data.TileState.bking);
                        else
                            DoMove(currentCell.Index(), CDest.Index(), GetState(currentCell.Index()));
                        complete = true;
                    }
                }
            }
            return complete;
        }
        void Tile_Click(object sender, EventArgs e)
        {
            TableLayoutPanelCellPosition tmp = BoardLayout.GetCellPosition((Control)sender);
            if (TurnSwitch == Data.TurnState.black)
            {
                ResetTileColor(currentCell.Index());
                if (ClickBlack_Move(Data.C(tmp.Row, tmp.Column)))
                {
                    txtStatus.Text = "White's Turn";
                    TurnSwitch = Data.TurnState.white;
                }
            }
            if (TurnSwitch == Data.TurnState.white)
            {
                ResetTileColor(currentCell.Index());
                if (ClickWhite_Move(Data.C(tmp.Row, tmp.Column)))
                {
                    txtStatus.Text = "Black's Turn";
                    TurnSwitch = Data.TurnState.black;
                }
            }
        }
        void ResetTile(int index)
        {
            Data.TileState src = BoardData[index];
        }
        public Data.TileState GetState(int id)
        {
            return BoardData[id];
        }
        public void SetTileColor(int id, Color what)
        {
            BoardLayout.Controls[id].BackColor = what;
        }
        // This function will cause errors if...
        //  -   CheckMove was not completed
        //  -   Incorrect parameters given
        // Always run CheckMove first!
        bool DoMove(int src, int dest, Data.TileState piece)
        {
            log("DoMove: from " + src + " to " + dest);
            //Replace BoardData
            SetState(src, Data.TileState.empty);
            //Update location
            SetState(dest, piece);
            return true;
        }
        Data.MoveType BlackMove(Data.Cell src, Data.Cell dest, bool king)
        {
            log("BlackMove: from" + src.Index() + " to " + dest.Index());
            Data.MoveType move = Data.MoveType.invalid;
            Data.TileState select = Data.TileState.empty;
            select = BoardData[Index(dest.row, dest.col)];
            //Take movements
            //Southwest
            if (dest.col == src.col - 2 && dest.row == src.row + 2)
            {
                Data.TileState cTake = GetState(Index(src.row + 1, src.col - 1));
                if (select == Data.TileState.empty && (cTake == Data.TileState.white || cTake == Data.TileState.wking))
                {
                    move = Data.MoveType.takeSW;
                }
            }
            //Southeast
            if (dest.col == src.col + 2 && dest.row == src.row + 2)
            {
                Data.TileState cTake = GetState(Index(src.row + 1, src.col + 1));
                if (select == Data.TileState.empty && (cTake == Data.TileState.white || cTake == Data.TileState.wking))
                {
                    move = Data.MoveType.takeSE;
                }
            }
            //Basic Movement    
            //Southwest
            if (dest.col == src.col - 1 && dest.row == src.row + 1)
            {
                if (select == Data.TileState.empty)
                {
                    move = Data.MoveType.SW;
                }
            }
            //Southeast
            if (dest.col == src.col + 1 && dest.row == src.row + 1)
            {
                if (select == Data.TileState.empty)
                {
                    move = Data.MoveType.SE;
                }
            }

            if(king)
            {
                //Take Northwest
                if (dest.col == src.col - 2 && dest.row == src.row - 2)
                {
                    Data.TileState cTake = GetState(Index(src.row - 1, src.col - 1));
                    if (select == Data.TileState.empty && (cTake == Data.TileState.white || cTake == Data.TileState.wking))
                    {
                        move = Data.MoveType.takeNW;
                    }
                }
                //Take Northeast
                if (dest.col == src.col + 2 && dest.row == src.row - 2)
                {
                    Data.TileState cTake = GetState(Index(src.row - 1, src.col + 1));
                    if (select == Data.TileState.empty && (cTake == Data.TileState.white || cTake == Data.TileState.wking))
                    {
                        move = Data.MoveType.takeNE;
                    }
                }
                //Northwest
                if (dest.col == src.col - 1 && dest.row == src.row - 1)
                {
                    if (select == Data.TileState.empty)
                    {
                        move = Data.MoveType.NW;
                    }
                }
                //Northeast
                if (dest.col == src.col + 1 && dest.row == src.row - 1)
                {
                    if (select == Data.TileState.empty)
                    {
                        move = Data.MoveType.NE;
                    }
                }
            }
            return move;
        }

        Data.MoveType WhiteMove(Data.Cell src, Data.Cell dest, bool king)
        {
            log("WhiteMove: from " + src.Index() + " to " + dest.Index());
            Data.MoveType move = Data.MoveType.invalid;
            Data.TileState select = Data.TileState.empty;
            select = BoardData[Index(dest.row, dest.col)];
            //Take movements
            //Take Northwest
            if (dest.col == src.col - 2 && dest.row == src.row - 2)
            {
                Data.TileState cTake = GetState(Index(src.row - 1, src.col - 1));
                if (select == Data.TileState.empty && (cTake == Data.TileState.black || cTake == Data.TileState.bking))
                {
                    move = Data.MoveType.takeNW;
                }
            }
            //Take Northeast
            if (dest.col == src.col + 2 && dest.row == src.row - 2)
            {
                Data.TileState cTake = GetState(Index(src.row - 1, src.col + 1));
                if (select == Data.TileState.empty && (cTake == Data.TileState.black || cTake == Data.TileState.bking))
                {
                    move = Data.MoveType.takeNE;
                }
            }
            //Northwest
            if (dest.col == src.col - 1 && dest.row == src.row - 1)
            {
                if (select == Data.TileState.empty)
                {
                    move = Data.MoveType.NW;
                }
            }
            //Northeast
            if (dest.col == src.col + 1 && dest.row == src.row - 1)
            {
                if (select == Data.TileState.empty)
                {
                    move = Data.MoveType.NE;
                }
            }

            if (king)
            {
                //Southwest
                if (dest.col == src.col - 1 && dest.row == src.row + 1)
                {
                    if (select == Data.TileState.empty)
                    {
                        move = Data.MoveType.SW;
                    }
                }
                //Southeast
                if (dest.col == src.col + 1 && dest.row == src.row + 1)
                {
                    if (select == Data.TileState.empty)
                    {
                        move = Data.MoveType.SE;
                    }
                }
                //Take south west
                if (dest.col == src.col - 2 && dest.row == src.row + 2)
                {
                    Data.TileState cTake = GetState(Index(src.row + 1, src.col - 1));
                    if (select == Data.TileState.empty && (cTake == Data.TileState.black || cTake == Data.TileState.bking))
                    {
                        move = Data.MoveType.takeSW;
                    }
                }
                //Take south east
                if (dest.col == src.col + 2 && dest.row == src.row + 2)
                {
                    Data.TileState cTake = GetState(Index(src.row + 1, src.col + 1));
                    if (select == Data.TileState.empty && (cTake == Data.TileState.black || cTake == Data.TileState.bking))
                    {
                        move = Data.MoveType.takeSE;
                    }
                }
            }
            return move;
        }

        public int Index(int row, int col)
        {
            return col + (row * 8);
        }
        void SetTileImage(int index, Bitmap image)
        {
            BoardLayout.Controls[index].BackgroundImage = image;
        }
        public void SetState(int index, Data.TileState value)
        {
            BoardData[index] = value;
            if (BoardLayout.Controls != null)
            {
                if (value == Data.TileState.black)
                {
                    SetTileImage(index, BlackPiece);
                }
                if (value == Data.TileState.bking)
                {
                    SetTileImage(index, BlackPieceK);
                }
                if (value == Data.TileState.white)
                {
                    SetTileImage(index, WhitePiece);
                }
                if (value == Data.TileState.wking)
                {
                    SetTileImage(index, WhitePieceK);
                }
                if (value == Data.TileState.empty)
                {
                    SetTileImage(index, imgEmpty);
                }
            }
        }
        //Reset tile background color
        public void ResetTileColor(int index)
        {
            Data.TileState tmp = GetState(index);
            if ((tmp & Data.TileState.cwhite) == Data.TileState.cwhite)
            {
                SetTileColor(index, BG);
            }
            else
            {
                SetTileColor(index, FG);
            }
        }
        public void LoadGame(Data.TileState[] file)
        { 
            
        }
        public void ResetTileColor(Data.Cell cell)
        {
            int id = cell.Index();
            ResetTileColor(id);
        }
        //Clear the Board data and other variables
        public void RestartGame()
        {
            int bEndIndex = 24,
            wStartIndex = 40;
            int seek = 0;
            BlackScore = 0;
            WhiteScore = 0;
            while (seek < 64)
            {
                BoardData[seek] = Data.TileState.empty;
                BoardLayout.Controls[seek].BackgroundImage = imgEmpty;
                seek++;
            }
            bool alternate = true;
            for (int y = 0; y < 8; y++)
            {
                if (alternate) alternate = false;
                else alternate = true;

                for (int x = 0; x < 8; x++)
                {
                    //Black pieces
                    if (Index(y, x) < bEndIndex)
                    {
                        if (alternate)
                        {
                            if (x % 2 == 1)
                            {
                                SetState(Index(y, x), Data.TileState.black);
                            }
                            else
                            {
                                SetState(Index(y, x), Data.TileState.empty);
                            }
                        }
                        else
                        {
                            if (x % 2 == 1)
                            {
                                SetState(Index(y, x), Data.TileState.empty);
                            }
                            else
                            {
                                SetState(Index(y, x), Data.TileState.black);
                            }
                        }
                    }
                    //White pieces
                    if (Index(y, x) > wStartIndex)
                    {
                        if (alternate)
                        {
                            if (x % 2 == 1)
                            {
                                SetState(Index(y, x), Data.TileState.white);
                            }
                            else
                            {
                                SetState(Index(y, x), Data.TileState.empty);
                            }
                        }
                        else
                        {
                            if (x % 2 == 1)
                            {
                                SetState(Index(y, x), Data.TileState.empty);
                            }
                            else
                            {
                                SetState(Index(y, x), Data.TileState.white);
                            }
                        }
                    }
                }
            }
        }
        //Pre-game setup for click events
        public void SetupGame()
        {
            bool alternate = true;
            for (int y = 0; y < 8; y++)
            {
                if (alternate) alternate = false;
                else alternate = true;
                for (int x = 0; x < 8; x++)
                {
                    BoardLayout.ColumnStyles[x].SizeType = SizeType.Percent;
                    BoardLayout.ColumnStyles[x].Width = 12.5F;
                    BoardLayout.RowStyles[y].SizeType = SizeType.Percent;
                    BoardLayout.ColumnStyles[y].Width = 12.5F;
                    Panel template = new Panel();
                    template.Margin = new System.Windows.Forms.Padding(1);
                    template.Padding = Padding.Empty;
                    template.BackgroundImageLayout = ImageLayout.Center;
                    template.Name = "cell" + x + "" + y;
                    if (alternate)
                    {
                        if (x % 2 == 1)
                        {
                            BoardData[Index(y, x)] |= Data.TileState.cblack;
                            template.BackColor = FG;
                        }
                        else
                        {
                            BoardData[Index(y, x)] |= Data.TileState.cwhite;
                            template.BackColor = BG;
                        }
                    }
                    else
                    {
                        if (x % 2 == 1)
                        {
                            BoardData[Index(y, x)] |= Data.TileState.cwhite;
                            template.BackColor = BG;
                        }
                        else
                        {
                            BoardData[Index(y, x)] |= Data.TileState.cblack;                            
                            template.BackColor = FG;
                        }
                    }
                    template.Dock = DockStyle.Fill;
                    template.Click += new EventHandler(Tile_Click);
                    BoardLayout.Controls.Add(template, x, y);
                }
            }
        }
        void log(object value)
        {
            Console.WriteLine(value);
        }
        //for testing only
        void ShowData()
        { 
            StringBuilder sb = new StringBuilder();
            Data.TileState tmp = Data.TileState.empty;
            string result = ".";
            for (int y = 0; y < 8; y++)
            {
                for (int x = 0; x < 8; x++)
                { 
                    tmp = BoardData[Index(y, x)];
                    if ((tmp & Data.TileState.white) == Data.TileState.white)
                    {
                        result = "P1";
                    }
                    if ((tmp & Data.TileState.black) == Data.TileState.black)
                    {
                        result = "P2";
                    }
                    if (tmp == Data.TileState.empty)
                    {
                        result = ".";
                    }
                    sb.Append(result + "\t");
                }
                sb.AppendLine();
            }
            MessageBox.Show(sb.ToString(), "Data Output");
        }
        private void mnuDebug_Click(object sender, EventArgs e)
        {
            ShowData();
        }

        private void BoardLayout_Paint(object sender, PaintEventArgs e)
        {

        }
    }        
}

